﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit;

namespace YArchitech.DataModel
{
	public class AuxiliaryLineOperate
	{
		public AuxiliaryLineOperate()
		{
			this.CopySettingFiles();
		}

		public AuxiliaryLineOperate(ExternalCommandData exCommand)
		{
			this.cmmData = exCommand;
			this.uiApp = this.cmmData.Application;
			this.uiDoc = this.uiApp.ActiveUIDocument;
			this.doc = this.uiDoc.Document;
			this.sel = this.uiDoc.Selection;
			this.view = this.doc.ActiveView;
			this.CopySettingFiles();
		}

		private void CopySettingFiles()
		{
			this.pathName = Path.Combine(Product.UserDataLocation, "HYSprinklerCheck.XML");
			this.boostpath = Path.Combine(new string[]
			{
				Product.UserDataLocation + "HYMarkCheck.xml"
			});
			try
			{
				if (!File.Exists(this.pathName))
				{
					File.Copy(Path.Combine(Product.DataLocation, "HYSprinklerCheck.XML"), this.pathName);
				}
				if (!File.Exists(this.boostpath))
				{
					File.Copy(Path.Combine(Product.DataLocation, "HYMarkCheck.XML"), this.boostpath);
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}

		public Dictionary<string, int> GetBoostSetting()
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (XElement xelement in XElement.Load(this.boostpath).Elements())
			{
				if (!(xelement.Name != "BoostLine"))
				{
					foreach (XAttribute xattribute in xelement.Attributes())
					{
						int value = Convert.ToInt32(xattribute.Value);
						string key = xattribute.Name.ToString();
						dictionary.Add(key, value);
					}
				}
			}
			return dictionary;
		}

		public void SaveBoostSetting(Dictionary<string, int> dicSet)
		{
			XElement xelement = XElement.Load(this.boostpath);
			foreach (XElement xelement2 in xelement.Elements())
			{
				if (!(xelement2.Name != "BoostLine"))
				{
					foreach (XAttribute xattribute in xelement2.Attributes())
					{
						foreach (KeyValuePair<string, int> keyValuePair in dicSet)
						{
							if (xattribute.Name.ToString() == keyValuePair.Key)
							{
								xattribute.SetValue(keyValuePair.Value);
							}
						}
					}
				}
			}
			xelement.Save(this.boostpath);
		}

		public DetailCurve DrawRangLine(FamilyInstance fi, double radius, string alGuid, int listNum = 1)
		{
			Document document = fi.Document;
			XYZ point = (fi.Location as LocationPoint).Point;
			DetailCurve detailCurve = YJKRevitTools.DrawRangLine(document, point, radius);
			if (string.IsNullOrEmpty(alGuid))
			{
				alGuid = "PTArrangeCheck";
			}
			this.SaveElementId(detailCurve.Id, alGuid);
			document.Regenerate();
			return detailCurve;
		}

		private void DiagonalLineFilledRegion(Autodesk.Revit.DB.Document document, Arc geomArc, ref ElementSet eSet, bool lineDir)
		{
			IList<XYZ> list = geomArc.Tessellate();
			int num;
			int num2;
			int num3;
			int num4;
			if (lineDir)
			{
				num = 0;
				num2 = list.Count / 4;
				num3 = list.Count - 2;
				num4 = num2 + 1;
				do
				{
					DetailCurve detailCurve = YJKRevitTools.DrawDetailLine(document, list[num], list[num2]);
					eSet.Insert(detailCurve);
					num += 2;
					num2 -= 2;
				}
				while (num < num2);
				do
				{
					DetailCurve detailCurve = YJKRevitTools.DrawDetailLine(document, list[num4], list[num3]);
					eSet.Insert(detailCurve);
					num4 += 2;
					num3 -= 2;
				}
				while (num4 < num3);
				return;
			}
			num = list.Count - 1;
			num2 = list.Count * 3 / 4;
			num3 = 0;
			num4 = num2 - 1;
			do
			{
				DetailCurve detailCurve = YJKRevitTools.DrawDetailLine(document, list[num], list[num2]);
				eSet.Insert(detailCurve);
				num -= 2;
				num2 += 2;
			}
			while (num2 < num);
			do
			{
				DetailCurve detailCurve = YJKRevitTools.DrawDetailLine(document, list[num4], list[num3]);
				eSet.Insert(detailCurve);
				num3 += 2;
				num4 -= 2;
			}
			while (num3 < num4);
		}

		private void SaveElementId(ElementId elemId, string alGuid)
		{
			try
			{
				XmlDocument xmlDocument = new XmlDocument();
				xmlDocument.Load(this.pathName);
				XmlNode xmlNode = xmlDocument.SelectSingleNode("ListDetailLine");
				XmlElement xmlElement = xmlDocument.CreateElement("DetailLine");
				xmlElement.InnerText = elemId.ToString();
				xmlElement.SetAttribute("dlType", alGuid);
				xmlNode.AppendChild(xmlElement);
				xmlDocument.Save(this.pathName);
			}
			catch (Exception)
			{
				throw;
			}
		}

		private List<string> GetDetailLineId(string alGuid)
		{
			List<string> list = new List<string>();
			try
			{
				XmlDocument xmlDocument = new XmlDocument();
				xmlDocument.Load(this.pathName);
				foreach (object obj in xmlDocument.SelectSingleNode("ListDetailLine").ChildNodes)
				{
					XmlNode xmlNode = (XmlNode)obj;
					if (!(xmlNode.Attributes["dlType"].Value.ToString() != alGuid))
					{
						list.Add(xmlNode.InnerText);
					}
				}
			}
			catch (Exception)
			{
				throw;
			}
			return list;
		}

		private void DeleteDetailLine(string alGuid)
		{
			try
			{
				XmlDocument xmlDocument = new XmlDocument();
				xmlDocument.Load(this.pathName);
				XmlNode xmlNode = xmlDocument.SelectSingleNode("ListDetailLine");
				List<XmlNode> list = new List<XmlNode>();
				foreach (object obj in xmlNode.ChildNodes)
				{
					XmlNode xmlNode2 = (XmlNode)obj;
					if (!(xmlNode2.Attributes["dlType"].Value.ToString() != alGuid))
					{
						list.Add(xmlNode2);
					}
				}
				foreach (XmlNode oldChild in list)
				{
					xmlNode.RemoveChild(oldChild);
				}
				xmlDocument.Save(this.pathName);
			}
			catch (Exception)
			{
				throw;
			}
		}

		public bool DeleteRangLine(Autodesk.Revit.DB.Document document, string alGuid, bool returnBool)
		{
			List<string> detailLineId = this.GetDetailLineId(alGuid);
			bool result;
			if (detailLineId.Count <= 0)
			{
				result = false;
			}
			else
			{
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
				filteredElementCollector.OfCategory(BuiltInCategory.OST_Lines);
				List<Element> list = new List<Element>();
				foreach (Element element in filteredElementCollector)
				{
					foreach (string b in detailLineId)
					{
						if (!(element.Id.ToString() != b))
						{
							list.Add(element);
						}
					}
				}
				if (list.Count <= 0)
				{
					result = false;
				}
				else
				{
					foreach (Element elem in list)
					{
						document.DeleteElement(elem);
					}
					this.DeleteDetailLine(alGuid);
					document.Regenerate();
					result = true;
					YJKMessageBox.Show("共删除" + list.Count.ToString() + "范围检查线!");
				}
			}
			return result;
		}

		public void DeleteRangLine(Autodesk.Revit.DB.Document document, string alGuid)
		{
			List<string> detailLineId = this.GetDetailLineId(alGuid);
			if (detailLineId.Count <= 0)
			{
				YJKMessageBox.Show("该视图没有您所要\n删除的范围检查线！");
				return;
			}
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
			filteredElementCollector.OfCategory(BuiltInCategory.OST_Lines);
			List<Element> list = new List<Element>();
			foreach (Element element in filteredElementCollector)
			{
				foreach (string b in detailLineId)
				{
					if (!(element.Id.ToString() != b))
					{
						list.Add(element);
					}
				}
			}
			if (list.Count <= 0)
			{
				return;
			}
			foreach (Element elem in list)
			{
				document.DeleteElement(elem);
			}
			this.DeleteDetailLine(alGuid);
			document.Regenerate();
		}

		public void DeleteBoostLine(Autodesk.Revit.DB.Document document, string alGuid, bool beBoostLine)
		{
			List<string> detailLineId = this.GetDetailLineId(alGuid);
			if (detailLineId.Count <= 0 && beBoostLine)
			{
				YJKMessageBox.Show("该视图没有您所要\n删除的辅助线！");
				return;
			}
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document);
			filteredElementCollector.OfCategory(BuiltInCategory.OST_Lines);
			List<Element> list = new List<Element>();
			foreach (Element element in filteredElementCollector)
			{
				foreach (string b in detailLineId)
				{
					if (!(element.Id.ToString() != b))
					{
						list.Add(element);
					}
				}
			}
			if (list.Count <= 0)
			{
				return;
			}
			foreach (Element elem in list)
			{
				document.DeleteElement(elem);
			}
			this.DeleteDetailLine(alGuid);
			document.Regenerate();
		}

		public bool DrawRectangleLine(double xSide, double ySide, double xDis, double yDis, string alGuid)
		{
			PickedBox pickedBox = this.sel.PickBox((Autodesk.Revit.UI.Selection.PickBoxStyle)0, "选择绘制区域……");
			XYZ min = pickedBox.Min;
			XYZ max = pickedBox.Max;
			IList<XYZ> diagonalPoint = YJKRevitTools.GetDiagonalPoint(min, max, xSide, ySide);
			Dictionary<XYZ, XYZ> dlendPoint = YJKRevitTools.GetDLEndPoint(diagonalPoint[0], diagonalPoint[1], xDis, yDis);
			if (dlendPoint.Count < 1)
			{
				return false;
			}
			ICollection<ElementId> collection = new List<ElementId>();
			foreach (KeyValuePair<XYZ, XYZ> keyValuePair in dlendPoint)
			{
				DetailLine detailLine = YJKRevitTools.DrawDetailLine(this.doc, keyValuePair.Key, keyValuePair.Value);
				this.SaveElementId(detailLine.Id, alGuid);
				collection.Add(detailLine.Id);
			}
			YJKRevitTools.SetDetailLineView(collection, this.cmmData);
			return true;
		}

		public bool DrawRectangleArc(double xSide, double ySide, double xDis, double yDis, string alGuid)
		{
			PickedBox pickedBox = this.sel.PickBox((Autodesk.Revit.UI.Selection.PickBoxStyle)0, "选择绘制区域……");
			XYZ min = pickedBox.Min;
			XYZ max = pickedBox.Max;
			IList<XYZ> diagonalPoint = YJKRevitTools.GetDiagonalPoint(min, max, xSide, ySide);
			IList<Dictionary<XYZ, XYZ>> dlendPoint = this.GetDLEndPoint(diagonalPoint[0], diagonalPoint[1], xDis, yDis);
			if (dlendPoint == null || dlendPoint.Count < 1)
			{
				return false;
			}
			ICollection<ElementId> collection = new List<ElementId>();
			foreach (KeyValuePair<XYZ, XYZ> keyValuePair in dlendPoint[0])
			{
				DetailCurve detailCurve = this.DrawCircleLine(keyValuePair.Key, keyValuePair.Value, this.GetArcRadius(keyValuePair.Key, keyValuePair.Value));
				this.SaveElementId(detailCurve.Id, alGuid);
				collection.Add(detailCurve.Id);
			}
			foreach (KeyValuePair<XYZ, XYZ> keyValuePair2 in dlendPoint[1])
			{
				DetailLine detailLine = YJKRevitTools.DrawDetailLine(this.doc, keyValuePair2.Key, keyValuePair2.Value);
				this.SaveElementId(detailLine.Id, alGuid);
				collection.Add(detailLine.Id);
			}
			YJKRevitTools.SetDetailLineView(collection, this.cmmData);
			return true;
		}

		private double GetArcRadius(XYZ pnt1, XYZ pnt2)
		{
			return pnt1.DistanceTo(pnt2) * 2.0;
		}

		public bool DrawDiamondLine(double xSide, double ySide, double xDis, double yDis, string alGuid)
		{
			XYZ onePoint = this.sel.PickPoint("请选择基准线起点……");
			XYZ twoPoint = this.sel.PickPoint("请选择基准线终点……");
			XYZ yPoint = this.sel.PickPoint("请选择范围框的边界点");
			IList<XYZ> diagonalPoint = YJKRevitTools.GetDiagonalPoint(onePoint, twoPoint, yPoint, xSide, ySide);
			Dictionary<XYZ, XYZ> dlendPoint = YJKRevitTools.GetDLEndPoint(diagonalPoint[0], diagonalPoint[1], diagonalPoint[2], xDis, yDis);
			if (dlendPoint.Count < 1)
			{
				return false;
			}
			ICollection<ElementId> collection = new List<ElementId>();
			foreach (KeyValuePair<XYZ, XYZ> keyValuePair in dlendPoint)
			{
				DetailLine detailLine = YJKRevitTools.DrawDetailLine(this.doc, keyValuePair.Key, keyValuePair.Value);
				this.SaveElementId(detailLine.Id, alGuid);
				collection.Add(detailLine.Id);
			}
			YJKRevitTools.SetDetailLineView(collection, this.cmmData);
			return true;
		}

		public bool DrawDiamondArc(double xSide, double ySide, double xDis, double yDis, string alGuid)
		{
			XYZ onePoint = this.sel.PickPoint("请选择基准线起点……");
			XYZ twoPoint = this.sel.PickPoint("请选择基准线终点……");
			XYZ yPoint = this.sel.PickPoint("请选择范围框的边界点");
			IList<XYZ> diagonalPoint = YJKRevitTools.GetDiagonalPoint(onePoint, twoPoint, yPoint, xSide, ySide);
			IList<Dictionary<XYZ, XYZ>> dlendPoint = this.GetDLEndPoint(diagonalPoint[0], diagonalPoint[1], diagonalPoint[2], xDis, yDis);
			if (dlendPoint.Count < 1)
			{
				return false;
			}
			ICollection<ElementId> collection = new List<ElementId>();
			foreach (KeyValuePair<XYZ, XYZ> keyValuePair in dlendPoint[1])
			{
				DetailCurve detailCurve = this.DrawCircleLine(keyValuePair.Key, keyValuePair.Value, this.GetArcRadius(keyValuePair.Key, keyValuePair.Value));
				this.SaveElementId(detailCurve.Id, alGuid);
				collection.Add(detailCurve.Id);
			}
			foreach (KeyValuePair<XYZ, XYZ> keyValuePair2 in dlendPoint[0])
			{
				DetailLine detailLine = YJKRevitTools.DrawDetailLine(this.doc, keyValuePair2.Key, keyValuePair2.Value);
				this.SaveElementId(detailLine.Id, alGuid);
				collection.Add(detailLine.Id);
			}
			YJKRevitTools.SetDetailLineView(collection, this.cmmData);
			return true;
		}

		public string DefineDetailLine(ModelLine line, string alGuid, ref ElementId elemId)
		{
			if (line == null)
			{
				return "没有选中模型线！";
			}
			Curve geometryCurve = line.GeometryCurve;
			DetailLine detailLine = this.doc.Create.NewDetailCurve(this.doc.ActiveView, geometryCurve) as DetailLine;
			if (detailLine == null)
			{
				return "定义辅助线没有成功！";
			}
			this.doc.DeleteElement(line);
			elemId = detailLine.Id;
			this.SaveElementId(elemId, alGuid);
			return "";
		}

		public XYZ GetCenterCircle(XYZ sPnt, XYZ ePnt, double radius, int radDir = 0)
		{
			XYZ xyz = new XYZ(sPnt.X, sPnt.Y, 0.0);
			XYZ xyz2 = new XYZ(ePnt.X, ePnt.Y, 0.0);
			XYZ xyz3 = xyz.Subtract(xyz2).Normalize();
			XYZ xyz4 = new XYZ(0.0, 0.0, 1.0);
			double num = sPnt.DistanceTo(ePnt) / 2.0;
			double num2 = Math.Sqrt(radius * radius - num * num);
			XYZ xyz5 = xyz3.CrossProduct(xyz4);
			XYZ xyz6 = sPnt.Add(ePnt) / 2.0;
			xyz6 = new XYZ(xyz6.X, xyz6.Y, sPnt.Z);
			XYZ result;
			if (radDir == 0)
			{
				result = xyz6.Subtract(num2 * xyz5).Add(radius * xyz5);
			}
			else
			{
				result = xyz6.Add(num2 * xyz5).Subtract(radius * xyz5);
			}
			return result;
		}

		public IList<Dictionary<XYZ, XYZ>> GetDLEndPoint(XYZ minPoint, XYZ maxPoint, double xDis, double yDis)
		{
			IList<Dictionary<XYZ, XYZ>> list = new List<Dictionary<XYZ, XYZ>>();
			Dictionary<XYZ, XYZ> dictionary = new Dictionary<XYZ, XYZ>();
			Dictionary<XYZ, XYZ> dictionary2 = new Dictionary<XYZ, XYZ>();
			double num = minPoint.X;
			double num2 = maxPoint.Y;
			if (xDis <= 0.0 && yDis <= 0.0)
			{
				return null;
			}
			if (xDis > 0.0)
			{
				do
				{
					XYZ value = new XYZ(num, minPoint.Y, 0.0);
					XYZ key = new XYZ(num, maxPoint.Y, 0.0);
					dictionary.Add(key, value);
					num += xDis;
				}
				while (num + xDis < maxPoint.X);
			}
			if (yDis > 0.0)
			{
				do
				{
					XYZ key2 = new XYZ(minPoint.X, num2, 0.0);
					XYZ value2 = new XYZ(maxPoint.X, num2, 0.0);
					dictionary2.Add(key2, value2);
					num2 -= yDis;
				}
				while (num2 > minPoint.Y);
			}
			list.Insert(0, dictionary);
			list.Insert(1, dictionary2);
			return list;
		}

		public IList<Dictionary<XYZ, XYZ>> GetDLEndPoint(XYZ xOnePoint, XYZ xTwoPoint, XYZ yPoint, double xDis, double yDis)
		{
			IList<Dictionary<XYZ, XYZ>> list = new List<Dictionary<XYZ, XYZ>>();
			Dictionary<XYZ, XYZ> dictionary = new Dictionary<XYZ, XYZ>();
			Dictionary<XYZ, XYZ> dictionary2 = new Dictionary<XYZ, XYZ>();
			double num = xOnePoint.DistanceTo(xTwoPoint);
			double num2 = yPoint.DistanceTo(xTwoPoint);
			XYZ xyz = (xTwoPoint - xOnePoint).Normalize();
			XYZ xyz2 = (yPoint - xTwoPoint).Normalize();
			XYZ xyz3 = new XYZ(0.0, 0.0, 0.0);
			XYZ xyz4 = new XYZ(0.0, 0.0, 0.0);
			double num3 = 0.0;
			double num4 = 0.0;
			if (xDis > 0.0)
			{
				do
				{
					xyz3 = xOnePoint + num3 * xyz;
					xyz4 = xOnePoint + num3 * xyz + num2 * xyz2;
					dictionary.Add(xyz4, xyz3);
					num3 += xDis;
				}
				while (num3 + xDis < num);
			}
			if (yDis > 0.0)
			{
				do
				{
					xyz3 = xOnePoint + num4 * xyz2;
					xyz4 = xTwoPoint + num4 * xyz2;
					dictionary2.Add(xyz3, xyz4);
					num4 += yDis;
				}
				while (num4 < num2);
			}
			list.Insert(0, dictionary);
			list.Insert(1, dictionary2);
			return list;
		}

		public DetailCurve DrawCircleLine(XYZ sPnt, XYZ ePnt, double radius)
		{
			XYZ centerCircle = this.GetCenterCircle(sPnt, ePnt, radius, 0);
			Curve curve = this.doc.CreatYJKArc(sPnt, ePnt, centerCircle);
			return this.doc.Create.NewDetailCurve(this.view, curve);
		}

		private ExternalCommandData cmmData;

		private UIApplication uiApp;

		private UIDocument uiDoc;

		private Document doc;

		private Selection sel;

		private Autodesk.Revit.DB.View view;

		private string pathName = "";

		private string boostpath = "";
	}
}
